package com.lin.carbon.utils;

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.util.Date;

/**
 * JWT 工具类，用于生成和验证 JWT Token，以及获取 Token 的过期时间
 */
@Component
public class JwtUtils {
    // 用于签名和验证 JWT 的密钥
    private final SecretKey secretKey;
    // Token 的过期时间，单位为毫秒，这里设置为 24 小时
    private static final long EXPIRATION_TIME = 86400000;

    /**
     * 构造函数，根据配置文件中的 jwt.secret 初始化密钥
     * @param secret 配置文件中配置的密钥
     */
    public JwtUtils(@Value("${jwt.secret}") String secret) {
        // 如果配置的密钥长度足够（至少 256 位），直接使用该密钥
        if (secret.length() * 8 >= 256) {
            this.secretKey = Keys.hmacShaKeyFor(secret.getBytes());
        } else {
            // 否则生成一个新的适合 HS256 算法的密钥
            this.secretKey = Keys.secretKeyFor(SignatureAlgorithm.HS256);
        }
    }

    /**
     * 生成 JWT Token
     * @param accountName 账户名，作为 Token 的主题
     * @return 生成的 JWT Token 字符串
     */
    public  String generateToken(String accountName) {
        return Jwts.builder()
                // 设置 Token 的主题为账户名
                .setSubject(accountName)
                // 设置 Token 的签发时间为当前时间
                .setIssuedAt(new Date())
                // 设置 Token 的过期时间为当前时间加上过期时长
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
                // 使用密钥和 HS256 算法对 Token 进行签名
                .signWith(secretKey, SignatureAlgorithm.HS256)
                // 构建并返回最终的 Token 字符串
                .compact();
    }

    /**
     * 验证 JWT Token 并获取其中的账户名
     * @param token 待验证的 JWT Token 字符串
     * @return 如果验证通过，返回 Token 中的账户名；否则返回 null
     */
    public  String validateToken(String token) {
        try {
            return Jwts.parserBuilder()
                    // 设置用于验证签名的密钥
                    .setSigningKey(secretKey)
                    // 构建 JWT 解析器
                    .build()
                    // 解析传入的 Token
                    .parseClaimsJws(token)
                    // 获取 Token 中的声明信息
                    .getBody()
                    // 获取声明信息中的主题，即账户名
                    .getSubject();
        } catch (Exception e) {
            // 验证失败，返回 null
            return null;
        }
    }

    /**
     * 获取 JWT Token 的过期时间
     * @param token 待获取过期时间的 JWT Token 字符串
     * @return 如果解析成功，返回 Token 的过期时间（毫秒）；否则返回 0
     */
    public long getTokenExpiration(String token) {
        try {
            return Jwts.parserBuilder()
                    // 设置用于验证签名的密钥
                    .setSigningKey(secretKey)
                    // 构建 JWT 解析器
                    .build()
                    // 解析传入的 Token
                    .parseClaimsJws(token)
                    // 获取 Token 中的声明信息
                    .getBody()
                    // 获取声明信息中的过期时间
                    .getExpiration()
                    // 将过期时间转换为毫秒数返回
                    .getTime();
        } catch (Exception e) {
            // 解析失败，返回 0
            return 0;
        }
    }
}
